<template>
  <div class="upload-file">
    <div class="clearfix">
      <div class="upload-file-list">
        <!-- 文件列表 -->
        <div :key="file.uid" class="el-upload-li" v-for="(file, index) in fileList">
          <div class="upload-head">
            <img v-if="file.isImage" class="img100" :src="file.url">
            <img v-else-if="file.type.toLowerCase() == 'xlsx' || file.type.toLowerCase() == 'xls'" class="upload-img"
              src="../../assets/file/xls.png">
            <img v-else-if="file.type.toLowerCase() == 'docx' || file.type.toLowerCase() == 'doc'" class="upload-img"
              src="../../assets/file/doc.png">
            <img v-else-if="file.type.toLowerCase() == 'pdf'" class="upload-img" src="../../assets/file/pdf.png">
            <img v-else class="upload-img" src="../../assets/file/wj.png">
            <el-tooltip class="item" effect="dark" :content="file.name" placement="top">
              <div class="upload-txt">
                <span>{{ file.name }}</span>
              </div>
            </el-tooltip>
          </div>
          <div class="upload-foot" v-if="isHandle">
            <div class="upload-fbtn" @click="previewFile(file, index)" v-if="file.isImage">
              <span class="upload-icon iconfont iconeye"></span>
              <span class="upload-itxt">预览</span>
            </div>
            <!-- <div class="upload-fbtn" @click="handleDwon(file)" v-if="type == '2'">
              <span class="upload-icon iconfont icondown"></span>
              <span class="upload-itxt">下载</span>
            </div> -->
            <div class="upload-fbtn" @click="handleDelete(index)">
              <span class="upload-icon iconfont icondel2"></span>
              <span class="upload-itxt">删除</span>
            </div>
          </div>
          <!-- 图片 -->
        </div>
        <!-- 失败列表 -->
        <div class="el-upload-li upload-fail" v-for="(file, index) in failList">
          <div class="upload-head">
            <img v-if="file.isImage" class="upload-img upload-img2" src="../../assets/file/img.png">
            <img v-else-if="file.type == 'xlsx' || file.type == 'xls'" class="upload-img"
              src="../../assets/file/xls.png">
            <img v-else-if="file.type == 'docx' || file.type == 'doc'" class="upload-img"
              src="../../assets/file/doc.png">
            <img v-else-if="file.type == 'pdf'" class="upload-img" src="../../assets/file/pdf.png">
            <img v-else="file.type=='pdf'" class="upload-img" src="../../assets/file/wj.png">
            <el-tooltip class="item" effect="dark" :content="file.name" placement="top">
              <div class="upload-txt">
                <span>{{ file.name }}</span>
              </div>
            </el-tooltip>
          </div>
          <div class="upload-foot">
            <!-- <div class="upload-fbtn" @click="handleFailDelete(index)">
              <span class="upload-icon iconfont icondel2"></span>
              <span class="upload-itxt">删除</span>
            </div> -->
          </div>
          <!--  -->
        </div>
        <!-- 上传 -->
        <div class="upload-box" v-show="limit > fileList.length">
          <!--  -->
          <!-- <div class="upload-loading" v-show="loading" v-loading="loading" :element-loading-text="loadingText"></div> -->
          <!-- 进度 -->
          <div class="upload-progress" v-if="isShowProgress">
            <el-progress type="circle" :percentage="percentage"></el-progress>
          </div>
          <!--  -->
          <!--  -->
          <!--  -->
          <el-upload :http-request="requestFun" :multiple="multiple" drag :before-upload="handleBeforeUpload"
            :file-list="fileList" :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed"
            :show-file-list="false" :headers="headers" class="upload-file-uploader" ref="fileUploadRef"
            v-show="limit > fileList.length" element-loading-background="#fff">
            <!-- 上传按钮 -->
            <el-button class="upload-file-btn" size="small" icon="el-icon-upload2" type="primary">{{ title
              }}</el-button>
            <!-- 显示文本 -->
            <div class="upload-show">
              <!-- 上传 -->
              <div class="upload-up">
                <img class="upload-img" src="../../assets/file/up.png" alt="">
                <div class="upload-txt">
                  <span>将文件拖到此处 或<span class="c189">点击上传</span></span>
                </div>
              </div>
            </div>
          </el-upload>
        </div>

      </div>
    </div>
    <!-- 上传提示 -->
    <div class="el-upload__tip" slot="tip" v-if="isShowTip" style="line-height: 1.2;">
      请上传
      <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
      <template v-if="uploadType"> 格式为 <b style="color: #f56c6c">{{ typeArr[typeIndex].arr.join("/") }}</b>
      </template>的文件
      <!-- <template v-if="limit"> 最多上传 <b style="color: #f56c6c">{{ limit }}个</b> </template> -->
    </div>
    <!-- 文件预览 -->
    <FilePreview ref="filePreviewRef"></FilePreview>
    <!--  -->
  </div>
</template>

<script setup>
import { upload } from '@/api/common'
import { ref, watch, computed, inject, onMounted } from 'vue'
import axios from 'axios'

import useUserStore from '@/store/modules/user'
let ossInfo = ref({});//阿里云oss信息
const userInfo = useUserStore();

const props = defineProps({
  modelValue: [String, Object, Array],
  // 上传接口地址
  action: {
    type: String,
    default: "/common/upload"
  },
  //是否可操作 - 底部工具菜单
  isHandle: {
    type: Boolean,
    default: true
  },
  // 上传携带的参数
  data: {
    type: Object
  },
  //是否支持多选文件
  multiple: {
    type: Boolean,
    default: true
  },
  // 数量限制
  limit: {
    type: Number,
    default: 5
  },
  // 大小限制(MB)
  fileSize: {
    type: Number,
    default: 500
  },
  // 文件类型, 例如['png', 'jpg', 'jpeg']
  fileType: {
    type: Array,
    default: () => ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf", "apk", 'png', 'jpg', 'jpeg']
  },
  // 是否显示提示
  isShowTip: {
    type: Boolean,
    default: true
  },
  // 禁用组件（仅查看文件）
  disabled: {
    type: Boolean,
    default: false
  },
  // 拖动排序
  drag: {
    type: Boolean,
    default: true
  },
  // 是否阿里云OSS
  ailiyunOss: {
    type: Boolean,
    default: false
  },
  //类型：验证类型的
  uploadType: {
    type: String,
    default: '1'
  },
  //标题
  title: {
    type: String,
    default: '上传附件',
  },
  //上传类型 image=图片 video=视频
  type: {
    type: String,
    default: 'image',
  },
})

const used = inject("used")
const emit = defineEmits()
const number = ref(0)
const uploadList = ref([])
const headers = ref()
const fileList = ref([]);
let failList = ref([]);//失败数组
let isShowProgress = ref(false);//是否显示进度条
let typeArr = ref([
  { type: '1', arr: ["png", "jpg", "jpeg", "webp", "gif"] },
  { type: '2', arr: ["apk"] },
  { type: '3', arr: ["video"] },
  // { type: '1', arr: ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf", "png", "jpg", "jpeg", 'zip', 'rar', '7z'] },
  // { type: '2', arr: ["xlsx"] },
  // { type: '3', arr: ['zip', 'rar', '7z'] },
  // { type: '5', arr: ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf", 'zip', 'rar', '7z'] },
]);
let typeIndex = ref(0);//验证类型 - 序号
let percentage = ref(0);//进度条
const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize))
//获取oss信息
const getOssInfo = async () => {
  ossInfo.value = await userInfo.getOssInfo();
}
if (props.ailiyunOss) {
  getOssInfo();
}

watch(() => props.modelValue, val => {
  if (val) {
    let temp = 1
    // 首先将值转为数组
    const list = Array.isArray(val) ? val : props.modelValue.split(',');
    // 然后将数组转为对象数组
    fileList.value = list.map(item => {
      if (typeof item === "string") {
        item = { name: item, url: item }
      }
      item.uid = item.uid || new Date().getTime() + temp++
      item.type = used.backType(item.url); //格式
      item.name = used.backAllName(item.url); //名称
      item.isImage = used.isImageType(item.url); //是否图片
      item.isVideo = used.isVideoType(item.url); //是否视频
      item.isApk = used.isApkType(item.url); //是否安装包
      return item
    })
  } else {
    fileList.value = []
    return []
  }
}, { deep: true, immediate: true })

let filePreviewRef = ref(null);
//预览
function previewFile(file, index) {
  if (file.isImage) {
    filePreviewRef.value.show(file.url);
  }
}
//获取验证格式
function getFileType() {
  //查询验证格式数组
  switch (props.uploadType) {
    case '1':
      typeIndex.value = 0;
      break;
    case '2':
      typeIndex.value = 1;
      break;
  }
}
// 上传前校检格式和大小
async function handleBeforeUpload(file) {
  let fileArrType = typeArr.value[typeIndex.value].arr;
  // 校检文件类型
  if (fileArrType.length) {
    const fileName = file.name.split('.')
    const fileExt = fileName[fileName.length - 1]
    const isTypeOk = fileArrType.indexOf(fileExt) >= 0;
    if (!isTypeOk) {
      used.msgError(`文件格式不正确，请上传${fileArrType.join("/")}格式文件!`)
      return false
    }
  }
  // 校检文件名是否包含特殊字符
  if (file.name.includes(',')) {
    used.msgError('文件名不正确，不能包含英文逗号!')
    return false
  }
  // 校检文件大小
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize
    if (!isLt) {
      used.msgError(`上传文件大小不能超过 ${props.fileSize} MB!`)
      return false
    }
  }
  // used.loading("正在上传文件，请稍候...")
  number.value++
  return true
}

// 文件个数超出
function handleExceed() {
  used.msgError(`上传文件数量不能超过 ${props.limit} 个!`)
}

let requestList = ref([]); //当前选择且准备上传的数据
//上传接口
async function requestFun(options) {
  let file = options.file;
  requestList.value.push({
    file: file,//文件信息
    name: file.name,//文件名称
    upStatus: 0,//默认上传失败
    uid: new Date().getTime(),//文件ID
    type: used.backType(file.name), //格式
    name: used.backAllName(file.name), //格式
    isImage: used.isImageType(file.name), //是否图片
    isVideo: used.isVideoType(file.name), //是否视频
    isApk: used.isApkType(file.name), //是否安装包
  });
  //阿里云OSS
  if (props.ailiyunOss) {
    httpALYRequest(options)
    return false;
  }
  //上传
  let formData = new FormData()
  formData.append('file', file);
  formData.append('type', props.type);
  let res = await upload(formData, {}, true);
  // res.data = res.data.file
  // options.onSuccess(res.data.file)
  handleUploadSuccess(res, file);
  isShowProgress.value = false
  //提交
  // let res = await upload(formData, this.progressFun);
  // this.handleUploadSuccess(res, file);
  // this.isShowProgress = false
}
const httpALYRequest = (options) => {
  const { file, onSuccess, onError, onProgress } = options;
  const formData = new FormData();
  formData.append('policy', ossInfo.value.policy);
  formData.append('x-oss-signature', ossInfo.value['signature']);
  formData.append('x-oss-signature-version', ossInfo.value['x_oss_signature_version']);
  formData.append('pox-oss-credentialicy', ossInfo.value['x_oss_credential']);
  formData.append('x-oss-date', ossInfo.value['x_oss_date']);
  formData.append('key', ossInfo.value['dir'] + options.file.name);
  formData.append('x-oss-security-token', ossInfo.value['security_token']);
  formData.append('x-oss-credential', ossInfo.value['x_oss_credential']);
  formData.append('file', file);
  axios.post(ossInfo.value.host, formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    //进度
    onUploadProgress: (progressEvent) => {
      progressFun(progressEvent)
      // let progres = parseInt(progressEvent.loaded / progressEvent.total * 100)
      // console.log(progres);
    },
  }).then((res) => {
    ///结果
    if (res.status == 204) {
      let url = 'https://download.yangtuoyou.com/' + ossInfo.value.dir + options.file.name;
      console.log(url);
      emit('update:modelValue', url)
      used.msgSuccess('上传成功')
      let rea = {
        code: 1,
        data: {
          url: url,
          name: options.file.name,
        }
      }
      handleUploadSuccess(rea, file);
      //成功
    } else {
      used.msgSuccess('上传失败')
    }
  })
}
//进度
function progressFun(e) {
  isShowProgress.value = true;
  let progress = parseInt((e.loaded / e.total) * 100);
  percentage.value = progress
  if (progress == 100) {
    isShowProgress.value = false
  }
}
// 上传失败
function handleUploadError(err) {
  used.msgError("上传文件失败")
  // used.closeLoading()
}
let fileUploadRef = ref(null);
// 上传成功回调
function handleUploadSuccess(res, file) {
  if (res.code === 1) {
    let data = res.data;
    uploadList.value.push({
      name: data.name,
      url: data.url,
      upStatus: 1,
      type: used.backType(data.url),
      name: used.backAllName(file.name), //格式
      isImage: used.isImageType(data.url),
      isVideo: used.isVideoType(file.name), //是否视频
      isApk: used.isApkType(file.name), //是否安装包
    })
    uploadedSuccessfully()
  } else {
    number.value--
    // used.closeLoading()
    used.msgError(res.message)
    fileUploadRef.handleRemove(file)
    uploadedSuccessfully()
  }
}

// 删除文件
function handleDelete(index) {
  fileList.value.splice(index, 1)
  emit("update:modelValue", listToString(fileList.value))
}

// 上传结束处理
function uploadedSuccessfully() {
  if (number.value > 0 && uploadList.value.length === number.value) {
    fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value)
    uploadList.value = []
    number.value = 0
    emit("update:modelValue", listToString(fileList.value))
    // used.closeLoading()
  }
}

// 获取文件名称
function getFileName(name) {
  // 如果是url那么取最后的名字 如果不是直接返回
  if (name.lastIndexOf("/") > -1) {
    return name.slice(name.lastIndexOf("/") + 1)
  } else {
    return name
  }
}

// 对象转成指定字符串分隔
function listToString(list, separator) {
  let strs = ""
  separator = separator || ","
  for (let i in list) {
    if (list[i].url) {
      strs += list[i].url + separator
    }
  }
  return strs != '' ? strs.substr(0, strs.length - 1) : ''
}

// 初始化拖拽排序
onMounted(() => {
  getFileType();

  // if (props.drag && !props.disabled) {
  //   nextTick(() => {
  //     const element = proxy.$refs.uploadFileList?.$el || proxy.$refs.uploadFileList
  //     Sortable.create(element, {
  //       ghostClass: 'file-upload-darg',
  //       onEnd: (evt) => {
  //         const movedItem = fileList.value.splice(evt.oldIndex, 1)[0]
  //         fileList.value.splice(evt.newIndex, 0, movedItem)
  //         emit('update:modelValue', listToString(fileList.value))
  //       }
  //     })
  //   })
  // }
})
</script>
<style scoped lang="scss">
.upload-file {
  position: relative;

  .upload-box {
    position: relative;
    float: left;
    margin-bottom: 10px;
    width: 180px;
    height: 160px;
  }

  :deep(.upload-progress) {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: #fff;
    border: 2px solid #F1F4F7;
    z-index: 61;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  :deep(.upload-loading) {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: #fff;
    border: 2px solid #F1F4F7;
    z-index: 6;

    .el-loading-spinner {
      top: 40px;
      margin-top: 0;

      .el-loading-text {
        font-size: 14px;
        color: #333333;
        line-height: 20px;
      }
    }
  }

  .upload-img {
    display: block;
    margin: 22px auto 0;
    width: 52px;
    height: 52px;

    &.upload-img2 {}
  }

  .upload-file-list {}
}

:deep(.upload-file-uploader) {
  width: 180px;
  height: 160px;
  background: #FFFFFF;
  border: 2px dashed #CEE7FF;
  border-radius: 4px;

  &:hover {
    border-color: #1890FF;
  }



  .el-upload {
    width: 100%;
    height: 100%;
  }

  .el-upload-dragger {
    width: 100%;
    height: 100%;
    border: none;
  }

  .upload-show {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    background-color: #fff;


    .upload-up {
      position: relative;
      width: 100%;
      height: 100%;
      overflow: hidden;



      .upload-txt {
        text-align: center;
        padding: 20px 40px 0;
        font-size: 14px;
        line-height: 1.6;
        color: #666666;
      }

      .c189 {
        color: #1890FF !important;
      }
    }
  }
}

.upload-file-list {
  position: relative;
  overflow: hidden;

  .el-upload-li {
    position: relative;
    margin-bottom: 10px;
    margin-right: 10px;
    display: flex;
    flex-direction: column;
    float: left;
    width: 180px;
    height: 160px;
    background: #FFFFFF;
    border: 2px solid #F1F4F7;
    border-radius: 4px;
    overflow: hidden;

    &.upload-fail {
      border: 2px solid #f00;

      .upload-icon {
        color: #f00;
      }

      .upload-itxt {
        color: #f00;
      }
    }

    .upload-icon {
      display: block;
      color: #666;
      font-size: 16px;
    }

    .upload-itxt {
      // display: none;
    }

    &:hover {
      .upload-icon {
        display: none;
      }

      .upload-itxt {
        display: block;
      }
    }

    .upload-head {
      flex: 1;
      overflow: hidden;

      .upload-txt {
        margin: 18px 5px 0;
        text-overflow: ellipsis;
        white-space: nowrap;
        overflow: hidden;
        font-size: 14px;
        text-align: center;
        color: #333333;
        line-height: 20px;
      }
    }

    .upload-foot {
      display: flex;
      height: 30px;
      background-color: #FAFAFC;

      .upload-fbtn {
        position: relative;
        display: flex;
        flex: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        color: #1890FF;
        font-size: 16px;
        border-right: 2px solid #F1F4F7;
        cursor: pointer;

        &:hover {
          opacity: 1;

          .upload-icon {
            display: none;
          }

          .upload-txt {
            display: block;
          }
        }

        &:last-child {
          border: none;
        }
      }
    }

    .el-icon-document {
      line-height: 1.6;
    }
  }

}

.upload-file-list .ele-upload-list__item-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: inherit;
}

.ele-upload-list__item-content-action .el-link {
  width: 40px;
  margin-right: 10px;
  white-space: nowrap;
}

:deep(.bc-heard) {
  .el-dialog__body {
    padding-top: 0;
  }
}

/*申报通知*/
.apply-upload {
  .upload-file-list {
    float: none;
  }

  .el-upload-li {
    margin-right: 0;
    width: 100%;
    height: 20px;
    border: none;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    background: none;

    .upload-head {
      .upload-img {
        display: none;
      }

      .upload-txt {
        margin: 0;
        text-align: left;
      }
    }

    .upload-foot {
      background: none;

      .upload-fbtn {
        opacity: 1;
        border: none;

        &:last-child {
          margin-left: 14px;

          .upload-itxt {
            color: #EE5850;
          }
        }

        .upload-icon {
          display: none;
        }

        .upload-itxt {
          display: inline-block;
          font-size: 14px;
        }
      }
    }
  }

  .upload-box {
    width: 80px;
    height: 28px;
    background: none;
    border: none;
    border-radius: 0;
    overflow: hidden;

    :deep(.upload-file-uploader) {
      width: 80px;
      height: 28px;
      border: none;
      border-radius: 0;
      background: none;

      .el-upload-dragger {
        background: none;
        border-radius: 2px;
      }

      .el-icon-upload2 {
        display: none;
      }

    }

    .upload-show {
      display: none;
    }
  }
}
</style>
